#pragma once
#include <iostream>
#include <vector>
#include <unistd.h>
#include <sys/wait.h>

class channel
{
public:
    channel(int wfd, int pid)
        : _wfd(wfd), _pid(pid)
    {
        _name = "Channel wfd : " + std::to_string(_wfd) + ", pid : " + std::to_string(pid);
    }
    ~channel() {}
    const std::string &getname()
    {
        return _name;
    }
    bool _send(int taskcode)
    {
        int n = write(_wfd, &taskcode, sizeof(taskcode));
        if (n < 0)
        { // 写入失败
            std::cerr << "write failed" << std::endl;
            return false;
        }
        // 写入成功
        return true;
    }
    void _close()
    {
        close(_wfd);
    }
    void _wait()
    {
        wait(nullptr);
    }

private:
    int _wfd;
    int _pid;
    std::string _name;
};

class channel_manage
{
public:
    channel_manage()
    {
    }
    ~channel_manage()
    {
    }
    void _insert(int wfd, int pid)
    {
        _channels.emplace_back(wfd, pid);
    }
    channel &_select()
    {
        auto &ret = _channels[_next];
        _next++;
        _next %= _channels.size();
        return ret;
    }
    void Print()
    {
        for (auto &channel : _channels)
        {
            std::cout << channel.getname() << std::endl;
        }
    }
    void _close()
    {
        for (auto &channel : _channels)
        {
            channel._close();
            std::cout << "关闭管道文件 : " << channel.getname() << std::endl;
        }
    }
    void _wait()
    {
        for (auto &channel : _channels)
        {
            channel._wait();
            std::cout << "等待子进程退出 : " << channel.getname() << std::endl;
        }
    }
    void _quit()
    {
        for (auto &channel : _channels)
        {
            channel._close();
            std::cout << "关闭管道文件 : " << channel.getname() << std::endl;
            channel._wait();
            std::cout << "等待子进程退出 : " << channel.getname() << std::endl;
        }
    }

private:
    std::vector<channel> _channels;
    int _next = 0;
};

class channel_pool
{
public:
    const int MAX_NUM = 5; // 进程池中进程的最大数量
    channel_pool()
        : _processnum(MAX_NUM)
    {
    }
    ~channel_pool()
    {
    }
    void _work(int rfd)
    {
        while (true)
        {
            int massage = 0;
            int n = read(rfd, &massage, sizeof(massage));
            if (n < 0)
            {
                std::cerr << "read failed" << std::endl;
                exit(1);
            }
            else if (n == 0)
            {
                std::cout << "exit, because write exit" << std::endl;
                break;
            }
            if (n != 4)
            {
                std::cout << "unkonw massage : " << massage << std::endl;
            }
            // 读取成功,执行任务
            std::cout << "receive massage : " << massage << std::endl;
        }
    }
    void send(int taskcode)
    {
        // 选择一个进程
        auto &c = _cm._select();
        std::cout << "选择进程 : " << c.getname() << ",发送信息 : " << taskcode << std::endl;
        // 任务码由上层调用决定
        // 发送信息
        c._send(taskcode);
    }
    void _init()
    {
        for (int i = 0; i < _processnum; i++)
        {
            int fd[2];
            int n = pipe(fd);
            if (n < 0)
            {
                std::cerr << "pipe failed" << std::endl;
                exit(1);
            }
            // 创建子进程
            int id = fork();
            if (id < 0)
            {
                std::cerr << "fork failed" << std::endl;
                exit(1);
            }
            else if (id == 0)
            {
                // child
                _cm._close();//关闭比子进创建早的子进程的写端
                close(fd[1]); // 关闭写端
                _work(fd[0]); // 等到父进程发送信息
                close(fd[0]);
                exit(1);
            }
            // parent
            close(fd[0]);
            // 在_cm中新增channel对象
            _cm._insert(fd[1], id);
        }
    }
    void _quit()
    {
        // // 关闭所有w端文件
        // _cm._close();
        // // 回收子进程
        // _cm._wait();
        _cm._quit();
    }
    void Print()
    {
        _cm.Print();
    }

private:
    channel_manage _cm;
    int _processnum;
};

// #pragma once
// #include <iostream>
// #include <vector>
// #include <unistd.h>
// #include <sys/wait.h>
// #include "task.hpp"
// // 管道
// class channel
// {
// public:
//     channel(int wfd, int pid)
//         : _wfd(wfd), _pid(pid)
//     {
//         _name = "channel wfd :" + std::to_string(wfd) + ",pid : " + std::to_string(pid);
//     }
//     const std::string &Name()
//     {
//         return _name;
//     }
//     void _send(int massage)
//     {
//         int n = write(_wfd, &massage, sizeof(massage));
//         if (n < 0)
//         {
//             std::cerr << "write failed" << std::endl;
//         }
//     }
//     // 关闭
//     void _close()
//     {
//         close(_wfd);
//     }
//     void _wait()
//     {
//         wait(nullptr);
//     }

// private:
//     int _wfd; // 写管道文件的文件描述符
//     int _pid; // 子进程pid
//     std::string _name;
// };
// // 组织管道文件
// class channel_manager
// {
// public:
//     void _insert(int fd, int pid)
//     {
//         _channels.emplace_back(fd, pid);
//     }
//     channel &_select()
//     {
//         auto &ret = _channels[_next];
//         _next++;
//         _next %= _channels.size();
//         return ret;
//     }
//     void Print()
//     {
//         for (auto channel : _channels)
//         {
//             std::cout << channel.Name() << std::endl;
//         }
//     }
//     // 关闭所有管道文件
//     void _close()
//     {
//         for (auto &channel : _channels)
//         {
//             channel._close();
//             // 关闭管道文件
//             //std::cout << "关闭管道文件 : " << channel.Name() << std::endl;
//         }
//     }
//     // 回收所有子进程
//     void _wait()
//     {
//         for (auto &channel : _channels)
//         {
//             channel._wait();
//             //std::cout << "回收子进程 : " << channel.Name() << std::endl;
//         }
//     }

// private:
//     std::vector<channel> _channels;
//     int _next = 0;
// };

// // 进程池
// class channel_pool
// {
// public:
//     const int MAX_NUM = 5;
//     channel_pool()
//         : _processnum(5)
//     {
//     }
//     // 子进程接受信息
//     void _word(int rfd)
//     {
//         while (true)
//         {
//             // 接受来自父进程的信息
//             int flag;
//             int n = read(rfd, &flag, sizeof(flag));
//             if (n < 0)
//             {
//                 std::cerr << "read failed" << std::endl;
//                 exit(1);
//             }
//             else if (n == 0)
//             {
//                 // std::cout<<"管道写端关闭，子进程也退出"<<std::endl;
//                 break;
//             }
//             if (n != 4)
//             {
//                 std::cout << "未知信息: " << flag << std::endl;
//                 continue;
//             }
//             // 执行任务
//             std::cout << "接受到一条信息: " << flag << std::endl;
//             _task._execute(flag);
//         }
//     }
//     // 父进程发信息
//     void send()
//     {
//         // 向哪一个管道/进程? 选一个管道文件
//         auto &c = _cm._select();
//         std::cout << "选择一个管道文件: " << c.Name() << std::endl;
//         // 发送哪一条信息
//         // 随便发
//         int x = rand() % 3;
//         std::cout << "发送信息 : " << x << std::endl;
//         c._send(x);
//     }
//     void _init()
//     {
//         // 创建进程池
//         for (int i = 0; i < _processnum; i++)
//         {
//             sleep(1);
//             // 父进程创建管道
//             int fd[2];
//             int n = pipe(fd);
//             if (n < 0)
//             {
//                 std::cerr << "pipe failed" << std::endl;
//                 exit(1);
//             }
//             // 创建子进程
//             int id = fork();
//             if (id < 0)
//             {
//                 std::cerr << "fork failed" << std::endl;
//                 exit(1);
//             }
//             else if (id == 0)
//             {
//                 // child
//                 // 关闭与自己无关的写端
//                 _cm._close();
//                 _cm.Print();
//                 std::cout << "-------------------" << std::endl;
//                 close(fd[1]); // 关闭写端
//                 _word(fd[0]); // 等待父进程传输信息执行对应任务
//                 close(fd[0]);
//                 exit(1);
//             }
//             // parent
//             close(fd[0]); // 关闭读端
//             _cm._insert(fd[1], id);
//         }
//     }
//     void _quit()
//     {
//         // 关闭所有管道文件
//         _cm._close();
//         // 回收所有子进程
//         _cm._wait();
//     }
//     void Print()
//     {
//         _cm.Print();
//     }

// private:
//     channel_manager _cm;
//     int _processnum; // 进程的个数
//     task _task;
// };